package me.zhengjie.modules.fund.reptile.impl;

import cn.hutool.core.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.modules.fund.domain.Fund;
import me.zhengjie.modules.fund.domain.FundNetValue;
import me.zhengjie.modules.fund.reptile.FundCrawler;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.springframework.data.domain.Pageable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * 天天基金实现类
 */
@Slf4j
@Component
public class FundEasyMoneyCrawler implements FundCrawler {

    @Resource
    private RestTemplate restTemplate;

    // 获取所有的基金列表
    public static final String GET_ALL_FUNDS_URL = "http://fund.eastmoney.com/js/fundcode_search.js";

    // 获取指定基金最近的净值
    public static final String GET_FUND_LASTED_DATA = "http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=%s";

    /**
     * 分页查询基金净值
     */
    public static final String GET_FUND_NET_VALUE_PAGE = "http://fund.eastmoney.com/f10/F10DataApi.aspx?type=lsjz&code=%s&page=%s&per=%s&sdate=%s";


    /**
     * @return
     * @see FundCrawler#getAllFunds()
     */
    @Override
    public List<Fund> getAllFunds() {
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(GET_ALL_FUNDS_URL, String.class);
        String response = responseEntity.getBody();
        String strFunds = response.substring(9);
        strFunds = strFunds.substring(0, strFunds.length() - 2);
        String[] split = strFunds.split("],");

        List<Fund> result = new LinkedList<>();
        for (String s : split) {
            String strFund = s.replace("[", "").replace("]", "");
            String[] fields = strFund.split(",");
            Fund fund = new Fund();
            fund.setCode(fields[0] == null ? "" : fields[0].replace("\"", ""));
            fund.setAbbr(fields[1] == null ? "" : fields[1].replace("\"", ""));
            fund.setName(fields[2] == null ? "" : fields[2].replace("\"", ""));
            fund.setCategory(fields[3] == null ? "" : fields[3].replace("\"", ""));
            fund.setPinyin(fields[4] == null ? "" : fields[4].replace("\"", ""));
            result.add(fund);
        }
        return result;
    }

    /**
     * @param code 基金编码
     * @return
     * @throws ParseException
     * @see FundCrawler#getLatestNetValues(String)
     */
    @Override
    public List<FundNetValue> getLatestNetValues(String code) throws ParseException {

        String url = String.format(GET_FUND_LASTED_DATA, code);

        return getFundNetValues(code, url);
    }

    private List<FundNetValue> getFundNetValues(String code, String url) throws ParseException {
        ResponseEntity<String> responseEntity = restTemplate.getForEntity(url, String.class);

        String detailTemp = responseEntity.getBody();

        String startStr = "var apidata={ content:\"";
        String recordStr = "\",records:";

        int recordIndex = detailTemp.lastIndexOf(recordStr);
        String detailStr = detailTemp.substring(0, recordIndex);

        detailStr = detailStr.replace(startStr, "");

        Document document = Jsoup.parse(detailStr);
        Elements elements = document.getElementsByTag("tr");

        List<FundNetValue> result = new ArrayList<>();
        for (int i = 1; i < elements.size(); i++) {
            Elements tds = elements.get(i).children();
            FundNetValue fundNetValue = new FundNetValue();
            fundNetValue.setCode(code);
            if (tds.get(0).text().equals("暂无数据!")) {
                break;
            }
            fundNetValue.setDate(DateUtils.parseDate(tds.get(0).text(), "yyyy-MM-dd"));
            fundNetValue.setNetValue(new BigDecimal(tds.get(1).text()));
            String strRate = tds.get(3).text().replace("%", "");
            if (StringUtils.isNotBlank(strRate)) {
                fundNetValue.setIncreaseRate(new BigDecimal(strRate).divide(BigDecimal.valueOf(100)));
            }
            fundNetValue.setBuyStatus(tds.get(4).text());
            fundNetValue.setSaleStatus(tds.get(5).text());
            result.add(fundNetValue);
        }
        return result;
    }

    /**
     * @param code 基金编码
     * @return
     * @throws ParseException
     * @see FundCrawler#getLatestNetValue(String)
     */
    @Override
    public FundNetValue getLatestNetValue(String code) throws ParseException {
        List<FundNetValue> latestNetValues = getLatestNetValues(code);
        if (CollectionUtils.isEmpty(latestNetValues)) {
            return null;
        }

        return latestNetValues.get(0);
    }

    @Override
    public List<FundNetValue> findFundNetValueByPage(String code, Pageable pageable, Date startDate) throws ParseException {
        if (Objects.isNull(startDate)) {
            startDate = DateUtil.beginOfYear(new Date());
        }
        String strStartDate = DateUtil.format(startDate, "yyyy-MM-dd");
        String url = String.format(GET_FUND_NET_VALUE_PAGE, code, pageable.getPageNumber(), pageable.getPageSize(), strStartDate);
        log.info("url {}", url);
        List<FundNetValue> fundNetValues = getFundNetValues(code, url);
        return fundNetValues;
    }
}
